package websocket

import (
	"log"
	"net/http"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		// 开发环境允许所有来源，生产环境应该验证域名白名单
		origin := r.Header.Get("Origin")
		// TODO: 生产环境应该配置允许的域名列表
		// allowedOrigins := []string{
		// 	"https://yourdomain.com",
		// 	"https://www.yourdomain.com",
		// }
		// for _, allowed := range allowedOrigins {
		// 	if origin == allowed {
		// 		return true
		// 	}
		// }
		// return false
		// 开发环境临时允许所有来源
		_ = origin // 避免未使用变量警告
		return true
	},
}

var WsHandler = NewWebSocketHandler(GetGlobalHub().GetHub())

// WebSocketHandler WebSocket处理器
type WebSocketHandler struct {
	hub *Hub
}

// NewWebSocketHandler 创建WebSocket处理器
func NewWebSocketHandler(hub *Hub) *WebSocketHandler {
	return &WebSocketHandler{
		hub: hub,
	}
}

// ConnectWebSocket 处理WebSocket连接（带JWT认证）
func (h *WebSocketHandler) ConnectWebSocket(c *gin.Context) {
	// 从context获取用户ID（需要JWT中间件）
	userId, exists := c.Get("userId")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "未授权"})
		return
	}

	// 安全的类型转换：支持 uint、uint64、string
	var userIdStr string
	switch v := userId.(type) {
	case uint:
		userIdStr = strconv.FormatUint(uint64(v), 10)
	case uint64:
		userIdStr = strconv.FormatUint(v, 10)
	case string:
		userIdStr = v
	case int:
		userIdStr = strconv.Itoa(v)
	case int64:
		userIdStr = strconv.FormatInt(v, 10)
	default:
		log.Printf("Warning: userId类型错误: %T, value: %v", userId, userId)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "用户ID类型错误"})
		return
	}

	if userIdStr == "" || userIdStr == "0" {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "用户ID无效"})
		return
	}

	// 检查连接数限制（可选）
	h.hub.mu.RLock()
	connectionCount := len(h.hub.clients)
	h.hub.mu.RUnlock()

	if connectionCount >= 10000 { // 最大连接数限制
		c.JSON(http.StatusServiceUnavailable, gin.H{"error": "服务器连接数已满"})
		return
	}

	// 升级HTTP连接为WebSocket
	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		log.Println("WebSocket升级失败:", err)
		return
	}

	// 创建客户端
	client := &Client{
		UserID: userIdStr,
		hub:    h.hub,
		conn:   conn,
		send:   make(chan []byte, 256), // 消息缓冲区
	}

	// 注册客户端
	h.hub.register <- client

	// 启动读写协程
	go client.readPump()
	go client.writePump()
}

// SendChatMessage 发送聊天消息
func (h *WebSocketHandler) SendChatMessage(c *gin.Context) {
	var req struct {
		ReceiverId string `json:"receiver_id" binding:"required"`
		Content    string `json:"content" binding:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"})
		return
	}

	// 从JWT获取发送者ID
	userId, exists := c.Get("userId")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "未授权"})
		return
	}

	senderIdStr := convertUserIdToString(userId)
	if senderIdStr == "" {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "用户ID无效"})
		return
	}

	message := ChatMessage{
		SenderId:    senderIdStr,
		Content:     req.Content,
		MessageType: 1,
		CreateTime:  time.Now().Format("2006-01-02 15:04:05"),
	}

	SendChatNotification(h.hub, req.ReceiverId, message)
	c.JSON(http.StatusOK, gin.H{"message": "发送成功"})
}

// SendMatchNotification 发送匹配通知
func (h *WebSocketHandler) SendMatchNotification(c *gin.Context) {
	var req struct {
		UserId  string `json:"user_id" binding:"required"`
		MatchId uint64 `json:"match_id" binding:"required"`
		Message string `json:"message"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"})
		return
	}

	SendMatchNotification(h.hub, req.UserId, req.MatchId, req.Message)
	c.JSON(http.StatusOK, gin.H{"message": "通知发送成功"})
}

// BroadcastMessage 广播消息
func (h *WebSocketHandler) BroadcastMessage(c *gin.Context) {
	var req struct {
		Message string `json:"message" binding:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"})
		return
	}

	h.hub.broadcast <- []byte(req.Message)
	c.JSON(http.StatusOK, gin.H{"message": "广播成功"})
}

// GetConnectedUsers 获取已连接用户列表
func (h *WebSocketHandler) GetConnectedUsers(c *gin.Context) {
	h.hub.mu.RLock()
	userIds := make([]string, 0, len(h.hub.userClients))
	for userId := range h.hub.userClients {
		userIds = append(userIds, userId)
	}
	h.hub.mu.RUnlock()

	c.JSON(http.StatusOK, gin.H{
		"users": userIds,
		"count": len(userIds),
	})
}

// convertUserIdToString 将各种类型的userId转换为string
func convertUserIdToString(userId interface{}) string {
	switch v := userId.(type) {
	case uint:
		return strconv.FormatUint(uint64(v), 10)
	case uint64:
		return strconv.FormatUint(v, 10)
	case string:
		return v
	case int:
		return strconv.Itoa(v)
	case int64:
		return strconv.FormatInt(v, 10)
	default:
		return ""
	}
}

